//
//  Params.h
//  RayTracer
//
//  Created by 俞云康 on 3/16/16.
//  Copyright © 2016 yushroom. All rights reserved.
//

#ifndef Params_h
#define Params_h
#include "Math.hpp"
#include "Color.hpp"
#include <map>
#include <vector>
#include <memory>
#include "pugixml.hpp"

using namespace std;

class Params
{
private:
    pugi::xml_node _node;
    
public:
    //Params(const ptree& tree);
    
    Params(const pugi::xml_node& xml_node) : _node(xml_node) {
    }
    
    Params(const Params& p) : _node(p._node) {
    }
    
    int     getIntAttribute(const string& name) const;
    int     getIntAttribute(const string& name, const int default_value, bool ignore_warning = false) const;
    
    float   getFloatAttribute(const string& name) const;
    float   getFloatAttribute(const string& name, const float default_value, bool ignore_warning = false) const;
    
    string  getStringAttribute(const string& name) const;
    string  getStringAttribute(const string& name, const string& default_value, bool ignore_warning = false) const;
    
    int     getInt() const;
    int     getInt(const string& name)const;

    float   getFloat() const;
    float   getFloat(const string& name) const;
    
    string  getString() const;
    string  getString(const string& name) const;
    
    float3  getFloat3() const;
    float3  getFloat3(const string& name) const;
    
    Color   getColor() const;
    Color   getColor(const string& name) const;

    
    string getType() const;
    string getName() const;
    string getID() const;
    string getRef() const;
    
    // get child node by type
    Params child(const string& type_name) const;
    
    void children(vector<string>& names, vector<Params>& ps) const;
    
    // get child node by name
    Params namedChild(const string& name) const;

	bool hasNamedChild(const string& name) const;

	bool hasTypedChild(const string& type) const;
};


class RootParams {
private:
    string _path;
    pugi::xml_document _doc;
public:
    RootParams(const string& xml_path) : _path(xml_path) {
        auto success = _doc.load_file(xml_path.c_str());
        if (!success) {
            error("Can not load xml file: %s\n   load result: %s\n", xml_path.c_str(), success.description());
            abort();
        }
    }
    
    Params child(const string& name) {
        return _doc.child(name.c_str());
    }
};

#endif /* Params_h */
